﻿#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

//strlen 统计的是字符串中\0之前的字符的个数
//int main()
//{
//	size_t len = strlen("abcdef");
//	printf("%zd", len);
//	return 0;
//}


//int main()
//{
//	char arr[] = "abcdef";
//	size_t len = strlen(arr);
//	printf("%zd\n", len);
//	return 0
//}


//strlen计算的\0是越界的，导致数值不确定
//err
//int main()
//{
//	int arr[3] = { 'a','b','c' };
//	size_t len = strlen(arr);
//	printf("%zd\n", len);
//	return 0;
//}


//int main()
//{
//	int a[] = { 1,2,3,4 };
//	printf("%zd\n", sizeof(a));//16  --sizeof(数组名)-计算的是数组的大小
//	printf("%zd\n", sizeof(a + 0));//a+0还是首元素的地址，sizeof(a+0)计算的是首元素地址大小4/8
//	printf("%zd\n", sizeof(*a));//*a 就是首元素,sizeof(*a)计算的是首元素的大小,4
//	printf("%zd\n", sizeof(a + 1));//a是首元素的地址，a+1是第二个元素的地址，sizeof(a+1)计算的是第二个元素地址的大小，4/8
//	printf("%zd\n", sizeof(a[1]));//a[1]就是第二个元素，sizeof(a[1])计算第二个元素的大小，4
//	printf("%zd\n", sizeof(&a));//&a --取出的是数组的地址，数组的地址也是地址，sizeof(&a)也是计算地址的大小,4/8
//	printf("%zd\n", sizeof(*&a));//1.&a是数组的地址，*&a其实相当于拿到了整个数组，计算的是整个数组的大小 -16
//	                             //2.*& == a    sizeof(*&a)=sizeof(a)  16
//
//
//	printf("%zd\n", sizeof(&a + 1));//&a+1是跳过整个数组后的那个地址，但也是地址，是地址就是4/8个字节
//	printf("%zd\n", sizeof(&a[0]));//&a[0]是首元素的地址，是地址就是4/8个字节
//	printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是首元素的地址，&a[0]+1就是第二个元素的地址，是地址就是4/8个字节
//}

//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%zd\n", sizeof(arr));//计算的是整个数组的大小，单位是字节，6
//	printf("%zd\n", sizeof(arr + 0));//arr是首元素的地址，arr+0还是首元素的地址，4/8
//	printf("%zd\n", sizeof(*arr));//arr是首元素的地址，*arr就是首元素，sizeof(*arr)计算的首元素的大小,1
//	printf("%zd\n", sizeof(arr[1]));//arr[1]是第二个元素，大小是1字节
//	printf("%zd\n", sizeof(&arr));//&arr取出的是数组的地址，但是数组的地址也是地址，是地址就是4/8个字节
//	printf("%zd\n", sizeof(&arr + 1));//&arr取出的是数组的地址，&arr+1是跳过数组后的那个地址，还是地址，大小4/8个字节
//	printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0]是首元素的地址，&arr[0]+1是第二个元素的地址，是地址大小4/8个字节
//	return 0;
//}


//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%zd\n", strlen(arr));//字符组中不包括\0,所以就会越界往后找\0,随机值
//	printf("%zd\n", strlen(arr + 0));//arr是首元素的地址，arr+0还是首元素的地址，从首元素开始向后统计,随机值
//	printf("%zd\n", strlen(*arr));//err  - arr是首元素的地址，*arr是首元素，'a'-97，这里是把97传给strlen,
//  strlen会将97作为地址，向后统计字符串长度，97作为地址的空间，不一定属于当前程序
//	printf("%zd\n", strlen(arr[1]));//arr[1]是'b'-98,98传给了strlen，也会非法访问 -- err
//	printf("%zd\n", strlen(&arr));//&arr是数组的地址，其实也是数组开始位置的编号，传递给strlen后，strlen一人是从首元素开始向后数字符
//  得到的还是随机值，因为没有\0
//	printf("%zd\n", strlen(&arr + 1));//随机值,因为没有\0
//	printf("%zd\n", strlen(&arr[0] + 1));//&arr[0]+1是第二个元素的地址，从这里向后数字符，还是随机值，因为没有\0
//	return 0;
//}


//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", sizeof(arr));//7
//	printf("%zd\n", sizeof(arr + 0));//4/8
//	printf("%zd\n", sizeof(*arr));//1
//	printf("%zd\n", sizeof(arr[1]));//1
//	printf("%zd\n", sizeof(&arr));//4/8
//	printf("%zd\n", sizeof(&arr + 1));//4/8
//	printf("%zd\n", sizeof(&arr[0] + 1));//4/8
//	return 0;
//}


//int main()
//{
//	char arr[] = "abcdef";
//	printf("%zd\n", strlen(arr));//6
//	printf("%zd\n", strlen(arr + 0));//6
//	printf("%zd\n", strlen(*arr));//err
//	printf("%zd\n", strlen(arr[1]));//err
//	printf("%zd\n", strlen(&arr));//6
//	printf("%zd\n", strlen(&arr + 1));//随机值
//	printf("%zd\n", strlen(&arr[0] + 1));//5
//	return 0;
//}


//int main()
//{
//	char* p = "abcdef";
//	printf("%zd\n", sizeof(p));//p是指针变量，计算的是指针变量的大小4/8
//	printf("%zd\n", sizeof(p + 1));//p中存放的是a的地址，p+1其实是b的地址 4/8
//	printf("%zd\n", sizeof(*p));//'a' -1
//	printf("%zd\n", sizeof(p[0]));//1.把常量字符串看作数组 p[0]就是第一个元素-'a'-1
//	//2.p[0]--*(p+0) -- *p - 'a' -- 1
//	printf("%zd\n", sizeof(&p));//4/8
//	printf("%zd\n", sizeof(&p + 1));//4/8
//	printf("%zd\n", sizeof(&p[0] + 1));//4/8
//	return 0;
//}


//int main()
//{
//	char* p = "abcdef";
//	printf("%zd\n", strlen(p));//6
//	printf("%zd\n", strlen(p + 1));//5
//	printf("%zd\n", strlen(*p));//*p - 'a' -97 //err
//	printf("%zd\n", strlen(p[0]));//err
//	printf("%zd\n", strlen(&p));//&*(p+0),随机值
//	printf("%zd\n", strlen(&p + 1));//随机值
//	printf("%zd\n", strlen(&p[0] + 1));//5
//	return 0;
//}


//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//3*4*sizeof(int) == 48
//	printf("%zd\n", sizeof(a[0][0]));//4
//	printf("%zd\n", sizeof(a[0]));//16 a[0]是第一行的数组名，现在单独放在sizeof内部，计算的是第一行的大小
//	printf("%zd\n", sizeof(a[0] + 1));//a[0]没有单独放在sizeof内部，a[0]表示第一行的这个一维数组首元素的地址->&a[0][0]
//	printf("%zd\n", sizeof(*(a[0] + 1)));//*(a[0]+1)是第一行第二个元素，4个字节
//	printf("%zd\n", sizeof(a + 1));//a作为二维数组的数组名，并没有单独放在sizeof中，所以a表示首元素的地址-那就是第一行的地址
//	                               //a+1 是跳过第一行，是第二行的地址，是地址就是4/8个字节
// 
//	printf("%zd\n", sizeof(*(a + 1)));
//	//1.a+1 是第二行的地址 -- int(*)[4], *(a+1)拿到的就是第二行，16个字节
//	//2.*(a+1) -- a[1]  sizeof(a[1]),计算的是第二行的大小，16个字节
// 
//	printf("%zd\n", sizeof(&a[0] + 1));//a[0]是第一行的数组名，&a[0]取出的是第一行的地址，&a[0]+1就是第二行的地址，是地址就是4/8个字节
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//对第二行的地址解引用，找到的就是第二行，16个字节
//	printf("%zd\n", sizeof(*a));//a表示首元素的地址，那就是第一行的地址，*a 就是第一行，计算的是第一行的大小 16个字节
//	                            //*a -- *(a+0) -- a[0]
//
//	printf("%zd\n", sizeof(a[3]));//不存在越界，因为不会真实的访问内存，仅仅是通过类型推导就可以知道长度，16
//	return 0;
//}


//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));
//	return 0;
//}


//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥？
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p = (struct Test*)0x100000;
//
//int main()
//{
//	printf("%p\n", p + 0x1);
//	printf("%p\n", (unsigned long)p + 0x1);
//	printf("%p\n", (unsigned int*)p + 0x1);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//	//                逗号表达式
//	// 1 3
//	// 5 0
//	// 0 0
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);
//	return 0;
//}


//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//	return 0;
//}